﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication3
{
    /// <summary>
    /// 按照步骤 1a 或 1b 操作，然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
    ///
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
    /// 元素中: 
    ///
    ///     xmlns:MyNamespace="clr-namespace:WpfApplication3"
    ///
    ///
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
    /// 元素中: 
    ///
    ///     xmlns:MyNamespace="clr-namespace:WpfApplication3;assembly=WpfApplication3"
    ///
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用，
    /// 并重新生成以避免编译错误: 
    ///
    ///     在解决方案资源管理器中右击目标项目，然后依次单击
    ///     “添加引用”->“项目”->[浏览查找并选择此项目]
    ///
    ///
    /// 步骤 2)
    /// 继续操作并在 XAML 文件中使用控件。
    ///
    ///     <MyNamespace:MarksLine/>
    ///
    /// </summary>
    public class MarksLine : Control
    {

        /// <summary>
        /// 第一个点
        /// </summary>
        public Point FirstPoint
        {
            get { return (Point)GetValue(FirstPointProperty); }
            set { SetValue(FirstPointProperty, value); }
        }

        // Using a DependencyProperty as the backing store for FirstPoint.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty FirstPointProperty =
            DependencyProperty.Register("FirstPoint", typeof(Point), typeof(MarksLine), new PropertyMetadata(new Point(0,50)));

        /// <summary>
        /// 第二个点
        /// </summary>
        public Point SecondPoint
        {
            get { return (Point)GetValue(SecondPointProperty); }
            set { SetValue(SecondPointProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SecondPoint.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SecondPointProperty =
            DependencyProperty.Register("SecondPoint", typeof(Point), typeof(MarksLine), new PropertyMetadata(new Point(50,0)));

        /// <summary>
        /// 第三个点
        /// </summary>
        public Point ThirdPoint
        {
            get { return (Point)GetValue(ThirdPointProperty); }
            set { SetValue(ThirdPointProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ThirdPoint.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ThirdPointProperty =
            DependencyProperty.Register("ThirdPoint", typeof(Point), typeof(MarksLine), new PropertyMetadata(new Point(100,50)));

        public MarksLine()
        {
            this.Loaded += MarksLine_Loaded;
        }

        void MarksLine_Loaded(object sender, RoutedEventArgs e)
        {
            AddThumb();

        }

        private Thumb thumb1, thumb2, thumb3;
        private void AddThumb()
        {
            Ellipse e1 = new Ellipse() { Width = 10, Height = 10, Fill = Brushes.Green };
            Ellipse e2 = new Ellipse() { Width = 16, Height = 16, Fill = Brushes.Green, Opacity = 0.5 };
            Canvas gd = this.Template.FindName("GdMain", this) as Canvas;
            gd.Children.Add(e1);
            gd.Children.Add(e2);
            thumb1 = new Thumb();
            thumb1.Width = 10;
            thumb1.Height=10;
            //thumb1.Margin = new Thickness(FirstPoint.X-thumb1.Width/2,FirstPoint.Y-this.thumb1.Height/2,0,0);
            Canvas.SetLeft(thumb1, FirstPoint.X - thumb1.Width / 2);
            Canvas.SetTop(thumb1, FirstPoint.Y - this.thumb1.Height / 2);
            thumb1.Template = GetResizeThumbControlTemplate();
            thumb1.HorizontalAlignment = HorizontalAlignment.Left;
            thumb1.VerticalAlignment = VerticalAlignment.Top;
            thumb1.DragDelta += thumb1_DragDelta;
            gd = this.Template.FindName("GdMain", this) as Canvas;
            gd.Children.Add(thumb1);
            e1.SetBinding(Canvas.LeftProperty, new Binding("(Canvas.Left)") { Source = thumb1 });
            e1.SetBinding(Canvas.TopProperty, new Binding("(Canvas.Top)") { Source = thumb1 });
            e2.SetBinding(Canvas.LeftProperty, new Binding("(Canvas.Left)") { Source = thumb1 });
            e2.SetBinding(Canvas.TopProperty, new Binding("(Canvas.Top)") { Source = thumb1 });
            thumb2 = new Thumb();
            thumb2.Width = 10;
            thumb2.Height = 10;
            //thumb2.Margin = new Thickness(this.SecondPoint.X - thumb2.Width / 2, SecondPoint.Y - this.thumb2.Height / 2, 0, 0);
            Canvas.SetLeft(thumb2, SecondPoint.X - thumb2.Width / 2);
            Canvas.SetTop(thumb2, SecondPoint.Y - this.thumb2.Height / 2);
            thumb2.Template = GetResizeThumbControlTemplate();
            thumb2.HorizontalAlignment = HorizontalAlignment.Left;
            thumb2.VerticalAlignment = VerticalAlignment.Top;
            thumb2.DragDelta += thumb2_DragDelta;
            gd = this.Template.FindName("GdMain", this) as Canvas;
            gd.Children.Add(thumb2);
            thumb3 = new Thumb();
            thumb3 = new Thumb();
            thumb3.Width = 10;
            thumb3.Height = 10;
            //thumb3.Margin = new Thickness(ThirdPoint.X - thumb3.Width / 2, ThirdPoint.Y - this.thumb3.Height / 2, 0, 0);
            Canvas.SetLeft(thumb3, ThirdPoint.X - thumb3.Width / 2);
            Canvas.SetTop(thumb3, ThirdPoint.Y - this.thumb3.Height / 2);
            thumb3.Template = GetResizeThumbControlTemplate();
            thumb3.HorizontalAlignment = HorizontalAlignment.Left;
            thumb3.VerticalAlignment = VerticalAlignment.Top;
            thumb3.DragDelta += thumb3_DragDelta;
            gd = this.Template.FindName("GdMain", this) as Canvas;
            gd.Children.Add(thumb3);
        }

        void thumb3_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Thumb mth = (Thumb)sender;
            double y = Canvas.GetTop(mth) + e.VerticalChange;
            double x = Canvas.GetLeft(mth) + e.HorizontalChange;
            Canvas.SetTop(mth, Canvas.GetTop(mth) + e.VerticalChange);
            Canvas.SetLeft(mth, Canvas.GetLeft(mth) + e.HorizontalChange);
            this.ThirdPoint = new Point(x+this.thumb3.Width/2,y+this.thumb3.Height/2);
        }

        void thumb2_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Thumb mth = (Thumb)sender;
            double y = Canvas.GetTop(mth) + e.VerticalChange;
            double x = Canvas.GetLeft(mth) + e.HorizontalChange;
            Canvas.SetTop(mth, Canvas.GetTop(mth) + e.VerticalChange);
            Canvas.SetLeft(mth, Canvas.GetLeft(mth) + e.HorizontalChange);
            this.SecondPoint = new Point(x + this.thumb2.Width / 2, y + this.thumb2.Height / 2);
        }

        void thumb1_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Thumb mth = (Thumb)sender;
            double y = Canvas.GetTop(mth) + e.VerticalChange;
            double x = Canvas.GetLeft(mth) + e.HorizontalChange;
            Canvas.SetTop(mth, Canvas.GetTop(mth) + e.VerticalChange);
            Canvas.SetLeft(mth, Canvas.GetLeft(mth) + e.HorizontalChange);
            this.FirstPoint = new Point(x + this.thumb1.Width / 2, y + this.thumb1.Height / 2);
        }
        private ControlTemplate GetResizeThumbControlTemplate()
        {
            var factory = new FrameworkElementFactory(typeof(Rectangle));
            factory.SetValue(Shape.FillProperty, Brushes.Black);
            factory.SetValue(Shape.StrokeProperty, Brushes.Black);
            var controlTemplate = new ControlTemplate { TargetType = typeof(Thumb), VisualTree = factory };
            
            return controlTemplate;
        }
        static MarksLine()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MarksLine), new FrameworkPropertyMetadata(typeof(MarksLine)));
        }
    }
}
